//
//  main.cpp
//  
//
//  Created by Kun Zhao on 12/05/29.
//  Copyright (c) 2012年 Kyoto University. All rights reserved.
//

#ifndef KVS__TIME_VARYING_CELL_BY_CELL_SAMPLING_H_INCLUDE
#define KVS__TIME_VARYING_CELL_BY_CELL_SAMPLING_H_INCLUDE

#include <kvs/MapperBase>
#include <kvs/Camera>
#include <kvs/PointObject>
#include <kvs/VolumeObjectBase>
#include <kvs/StructuredVolumeObject>
#include <kvs/UnstructuredVolumeObject>
#include <kvs/ClassName>
#include <kvs/Module>
#include <kvs/CellByCellParticleGenerator>
#include <kvs/BitArray>

typedef unsigned char PTtype;

namespace kvs
{

/*===========================================================================*/
/**
 *  @brief  Cell-by-cell particle generation class.
 */
/*===========================================================================*/
class TimeVaryingCellByCellSampling : public kvs::MapperBase, public kvs::PointObject
{
    // Class name.
    kvsClassName( kvs::TimeVaryingCellByCellSampling );

    // Module information.
    kvsModuleCategory( Mapper );
    kvsModuleBaseClass( kvs::MapperBase );
    kvsModuleSuperClass( kvs::PointObject );

private:

    const kvs::Camera*     m_camera;         ///< camera (reference)
    size_t                 m_subpixel_level; ///< subpixel level
    float                  m_sampling_step;  ///< sampling step in the object coordinate
    float                  m_object_depth;   ///< object depth
    kvs::ValueArray<float> m_density_map;    ///< density map
    
    kvs::BitArray*         m_CT; // celss table of this step
    std::vector<PTtype>*   m_PT; // particle table of this step
    bool                   m_is_first_step; // set whether it is first step or not
    long long              m_CT_loc; // the location in the CT bit file

public:

    TimeVaryingCellByCellSampling( void );

    TimeVaryingCellByCellSampling(
        const kvs::VolumeObjectBase* volume,
        const size_t                 subpixel_level,
        const float                  sampling_step,
        const kvs::TransferFunction& transfer_function,
        const float                  object_depth = 0.0f );

    TimeVaryingCellByCellSampling(
        const kvs::Camera*           camera,
        const kvs::VolumeObjectBase* volume,
        const size_t                 subpixel_level,
        const float                  sampling_step,
        const kvs::TransferFunction& transfer_function,
        const float                  object_depth = 0.0f );

    virtual ~TimeVaryingCellByCellSampling( void );

public:

    SuperClass* exec( const kvs::ObjectBase* object );

public:

    const size_t subpixelLevel( void ) const;

    const float samplingStep( void ) const;

    const float objectDepth( void ) const;

    void attachCamera( const kvs::Camera* camera );

    void setSubpixelLevel( const size_t subpixel_level );

    void setSamplingStep( const float sampling_step );

    void setObjectDepth( const float object_depth );
    
    void setCellsTable( kvs::BitArray* CT, long long loc );
    
    void setParticlesTable( std::vector<PTtype>* PT );
    
    PTtype* particlesTable( void );
    
    void isFirstStep();
    
    void notFirstStep();

private:

    void mapping( const kvs::Camera* camera, const kvs::StructuredVolumeObject* volume );

    void mapping( const kvs::Camera* camera, const kvs::UnstructuredVolumeObject* volume );

    template <typename T>
    void generate_particles( const kvs::StructuredVolumeObject* volume );

    template <typename T>
    void generate_particles( const kvs::UnstructuredVolumeObject* volume );
};
    
} // end of namespace kvs

#endif // KVS__TIME_VARYING_CELL_BY_CELL_SAMPLING_H_INCLUDE
